package com.example.concurrency.exercise;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author: dangwen
 * @createDate: 2021/2/3
 * 《wait/notify实现生产者和消费者程序》
 * 采用多线程技术，例如wait/notify，设计实现一个符合生产者和消费者问题的程序，对某一个对象（枪膛）进行操作，其最大容量是20颗子弹，生产者线程是一个压入线程，它不断向枪膛中压入子弹，
 * 消费者线程是一个射出线程，它不断从枪膛中射出子弹。 请实现上面的程序。
 */
public class ThreadExercise01 {

    private static final Integer MAX = 20;
    private static final Integer MIN = 0;

    private int num;

    public ThreadExercise01(Integer num){
        this.num = num;
    }

    synchronized void input(){
        while (num >=20 ){
            try {
                System.out.println(Thread.currentThread().getName()+"枪膛已满"+num);
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        num++;
        System.out.println(Thread.currentThread().getName()+"--------填入了一颗子弹："+num);
        notifyAll();
    }

    synchronized void output(){
        while (num < 1){
            try {
                System.out.println(Thread.currentThread().getName()+"枪膛已空"+num);
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        num--;
        System.out.println(Thread.currentThread().getName()+"--------射出了一颗子弹："+num);
        notifyAll();
    }

    public static void main(String[] args) {
        ThreadExercise01 threadExercise01 = new ThreadExercise01(10);
        new Thread(new Shoot(threadExercise01)).start();
        new Thread(new Load(threadExercise01)).start();
    }
}

class Shoot implements Runnable{
    private ThreadExercise01 threadExercise01;
    public Shoot(ThreadExercise01 threadExercise01){
        this.threadExercise01 = threadExercise01;
    }

    @Override
    public void run() {
        while (true){
            threadExercise01.output();
        }
    }
}

class Load implements Runnable{
    private ThreadExercise01 threadExercise01;
    public Load(ThreadExercise01 threadExercise01){
        this.threadExercise01 = threadExercise01;
    }

    @Override
    public void run() {
        while (true){
            threadExercise01.input();
        }
    }
}